//
//  Http.swift
//  MintBag
//
//  Created by wy on 2024/8/23.
//

import Foundation
import Alamofire
import CryptoSwift

typealias ResponseClosure = (_ response: [String: Any]) -> Void

class Http {
    static let shared = Http()
    let manager: Session!
    let responseQueue = DispatchQueue.global(qos: .utility)

    init() {
        let configuration = URLSessionConfiguration.default
        configuration.httpMaximumConnectionsPerHost = 50
        configuration.timeoutIntervalForRequest = 30
        manager = Alamofire.Session(configuration: configuration)
    }
    
    func requestApi(_ api: Api, responseClosure: ResponseClosure? = nil) {
        let url = URL(string: api.domain + api.service + Http.aesEncrypt(api.path))!
        print("api.path=======>\(api.path)")
        var request = URLRequest(url: url)
        request.httpMethod = api.method
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        for (k, v) in api.headers {
            request.setValue("\(v)", forHTTPHeaderField: k)
        }
        let parameters: [String: Any] = api.parameters
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
            if let jsonString = String(data: jsonData, encoding: .utf8) {
                if let data = Http.aesEncrypt(jsonString).data(using: .utf8) {
                    request.httpBody = data
                }
            }
        } catch {
            print("Error serializing JSON: \(error.localizedDescription)")
        }
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                Async.main {
                    responseClosure?(["code": 0, "message": "Error: \(error.localizedDescription)"])
                }
                return
            }
            if let data = data {
                if let responseString = String(data: data, encoding: .utf8) {
                    let str = Http.aesdecrypt(responseString)
                    if let jsonData = str.data(using: .utf8) {
                        do {
                            if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                                Async.main {
                                    // 拦截token失效
                                    if json["code"] as? Int == 411 || json["code"] as? Int == 2021 {
                                        KeychainStore.shared.remove(forKey: .sessionId)
                                        KeychainStore.shared.remove(forKey: .userId)
                                        KeychainStore.shared.remove(forKey: .userPhone)
                                        KeychainStore.shared.remove(forKey: .userInfo)
                                        NotificationCenter.default.post(name: NSNotification.Name(Const.loginStatusChanged), object: nil)
                                    }
                                    responseClosure?(json)
                                }
                            }
                        } catch {
                            Async.main {
                                responseClosure?(["code": 0, "message": "JSON 解析失败: \(error)"])
                            }
                        }
                    } else {
                        Async.main {
                            responseClosure?(["code": 0, "message": "无法将字符串转换为 Data"])
                        }
                    }
                }
            }else {
                Async.main {
                    responseClosure?(["code": 0, "message": "返回Data为空"])
                }
            }
        }
        task.resume()
    }
    
    func requestUploadApi(_ api: Api, fileData: Data, responseClosure: ResponseClosure? = nil) {
        let url = URL(string: api.domain + api.service + api.path)
        let parameters: [String: String] = [
            "type": "jpg"
        ]
        AF.upload(multipartFormData: { multipartFormData in
            // 添加文件数据
            multipartFormData.append(fileData, withName: "file", fileName: "upload.jpg", mimeType: "image/jpeg")
            // 添加其他参数
            for (key, value) in parameters {
                if let valueData = value.data(using: .utf8) {
                    multipartFormData.append(valueData, withName: key)
                }
            }
        }, to: url!, headers: HTTPHeaders(api.headers))
        .response { response in
            // 检查请求结果
            switch response.result {
            case .success:
                if let json = try? JSONSerialization.jsonObject(with: response.data!, options: []) as? [String: Any] {
                    Async.main {
                        responseClosure?(json)
                    }
                }
                print("上传成功")
            case let .failure(error):
                responseClosure?(["code": 0, "message": "上传失败: \(error)"])
                print("上传失败: \(error)")
            }
        }
    }
    
    static func aesEncrypt(_ req: String, secretKey: String = "e6ka+kzmWA1AgEv6", iv: String = "0000000000000000") -> String{
        var encryptedBase64 = ""
        do {
            let aes = try AES(key: secretKey.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7)
            let encrypted = try aes.encrypt(req.bytes)
            encryptedBase64 = encrypted.toBase64() ?? "" //将加密结果转成base64形式
        } catch { }
        
        return encryptedBase64
    }
    
    static func aesdecrypt(_ res: String, secretKey: String = "e6ka+kzmWA1AgEv6", iv: String = "0000000000000000") -> String{
        var decryptStr = ""
        if let encryptedData = Data(base64Encoded: res) {
            do {
                // 初始化AES对象，设置 CBC 模式和 PKCS7 填充
                let aes = try AES(key: secretKey.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7)
                let decryptedBytes = try aes.decrypt(encryptedData.bytes)
                if let decryptedString = String(bytes: decryptedBytes, encoding: .utf8) {
                    decryptStr = decryptedString
                } else {
                    print("无法将解密后的数据转换为字符串")
                }
            } catch {
                print("解密失败: \(error)")
            }
        } else {
            print("Base64解码失败")
        }

        return decryptStr
    }

}

